#ifndef THREADPOOL_H
#define THREADPOOL_H
#include <mutex>
#include <condition_variable>
#include <queue>
#include <thread>
#include <functional>
#include <assert.h>
/*explicit:禁止隐式转换*/
class ThreadPool {
public:
    explicit ThreadPool(size_t threadCount = 8): pool_(std::make_shared<Pool>()) {
        assert(threadCount > 0);
        /* detach: 主调线程无法再取得该被调线程的控制权*/

        // 这个线程池还是依次执行的呗
        for(size_t i = 0; i < threadCount; i++) {
            std::thread([pool = pool_] {
                std::unique_lock<std::mutex> locker(pool->mtx);
                while(true) {
                    if(!pool->tasks.empty()) {
                        /*因为多个线程共享这个队列所以要加锁*/
                        auto task = std::move(pool->tasks.front());
                        pool->tasks.pop();
                        locker.unlock();
                        task();
                        locker.lock();
                    }
                    else if(pool->isClosed) break;
                    else pool->cond.wait(locker);
                }

            }).detach();
        }
    }
    /*允许出现赋值这种浅拷贝的行为*/
    ThreadPool() = default;                       // 默认构造函数
    ThreadPool(ThreadPool&&) = default;           // 移动构造函数

    ~ThreadPool() {
        if(static_cast<bool>(pool_)) {
            {
                std::lock_guard<std::mutex> locker(pool_->mtx);
                pool_->isClosed = true;
            }
            pool_->cond.notify_all();
        }
    }

    template<class F>
    /*右值引用*/
    void AddTask(F&& task) {
        {
            std::lock_guard<std::mutex> locker(pool_->mtx);
            /*forward的含义*/
            /*根据参数的原始值类别（是否为左值），将其转为对应的引用类型（左值引用 T& 或右值引用 T&&），确保目标函数接收到正确的参数类型*/
            pool_->tasks.emplace(std::forward<F>(task));
        }
        pool_->cond.notify_one();
    }
private:
    /*池子里面有各种各样需要执行的函数*/
    struct Pool {
        std::mutex mtx;
        std::condition_variable cond;
        bool isClosed;
        std::queue<std::function<void()>> tasks;
    };
    /*存在引用计数*/
    /*这是个指针 传给了池子里所有的线程*/
    std::shared_ptr<Pool> pool_;
};
#endif